package net.jiastudy.biz.assessment.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import net.jiastudy.biz.assessment.entity.AssessDetailTreeVo;
import net.jiastudy.biz.assessment.entity.Assessment;
import net.jiastudy.biz.assessment.entity.AssessmentCreateVo;
import net.jiastudy.biz.assessment.entity.AssessmentDetail;
import net.jiastudy.biz.assessment.entity.AssessmentDetailShowVo;
import net.jiastudy.biz.assessment.entity.AssessmentDetailVo;
import net.jiastudy.biz.assessment.entity.AssessmentPerson;
import net.jiastudy.biz.assessment.entity.AssessmentPersonCreateVo;
import net.jiastudy.biz.assessment.entity.AssessmentScore;
import net.jiastudy.biz.assessment.mapper.AssessmentDetailMapper;
import net.jiastudy.biz.assessment.mapper.AssessmentMapper;
import net.jiastudy.biz.assessment.mapper.AssessmentPersonMapper;
import net.jiastudy.biz.assessment.mapper.AssessmentScoreMapper;
import net.jiastudy.biz.assessment.service.AssessmentService;
import net.jiastudy.biz.targettask.entity.TargetTask;
import net.jiastudy.biz.targettask.entity.TaskReportVo;
import net.jiastudy.biz.targettask.entity.TaskYear;
import net.jiastudy.biz.targettask.service.TargetTaskService;
import net.jiastudy.biz.user.entity.User;
import net.jiastudy.biz.user.service.UserService;
import net.jiastudy.core.base.BaseService;
import net.jiastudy.core.exception.ServiceException;
import net.jiastudy.core.utils.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;


@Service
public class AssessmentServiceImpl extends BaseService<AssessmentMapper, Assessment> implements AssessmentService {
    @Resource
    private AssessmentPersonMapper assessmentPersonMapper;
    @Resource
    private AssessmentScoreMapper assessmentScoreMapper;
    @Resource
    private AssessmentDetailMapper assessmentDetailMapper;
    @Resource
    private UserService userService;
    @Resource
    private TargetTaskService targetTaskService;

    @Override
    public void addAssessment(AssessmentCreateVo assessmentCreateVo) {
        if (!assessmentCreateVo.getAssessmentDept().isEmpty()) {
            for (AssessmentPersonCreateVo assessmentPersonCreateVo : assessmentCreateVo.getAssessmentDept()) {
                Assessment assessment = new Assessment();
                assessment.setAssessmentedDeptId(assessmentCreateVo.getAssessmentedDeptId());
                assessment.setAssessmentDeptId(assessmentPersonCreateVo.getId());
                assessment.setYear(assessmentCreateVo.getYearId());
                assessment = createAssessment(assessment);

                if (!assessmentPersonCreateVo.getPerson().isEmpty()) {
                    for (Long userId : assessmentPersonCreateVo.getPerson()) {
                        AssessmentPerson assessmentPerson = new AssessmentPerson();
                        assessmentPerson.setUserId(userId);
                        assessmentPerson.setAssessmentId(assessment.getId());
                        assessmentPersonMapper.insert(assessmentPerson);
                    }
                }
            }
        }
    }

    @Override
    public void updateAssessmentPerson(AssessmentPersonCreateVo assessmentPersonCreateVo) {
        EntityWrapper<AssessmentPerson> ew = new EntityWrapper<>();
        ew.eq("assessment_id", assessmentPersonCreateVo.getAssessmentId());
        assessmentPersonMapper.delete(ew);

        if (assessmentPersonCreateVo.getPerson().isEmpty()){
            return ;
        }

        for (Long userId : assessmentPersonCreateVo.getPerson()) {
            AssessmentPerson assessmentPerson = new AssessmentPerson();
            assessmentPerson.setUserId(userId);
            assessmentPerson.setAssessmentId(assessmentPersonCreateVo.getId());
            assessmentPersonMapper.insert(assessmentPerson);
        }
    }

    @Override
    public Assessment createAssessment(Assessment assessment) {
        Wrapper<Assessment> wrapper = new EntityWrapper<>();
        wrapper.eq("assessment_dept_id", assessment.getAssessmentDeptId());
        wrapper.eq("assessmented_dept_id", assessment.getAssessmentedDeptId());
        wrapper.eq("year", assessment.getYear());
        Assessment dbAssessment = this.selectOne(wrapper);
        if (null != dbAssessment) {
            throw new ServiceException("该考核已经设置");
        }

        if (this.insert(assessment)) {
            return assessment;
        }

        return null;
    }

    @Override
    public Page<Assessment> searchAssessments(Page<Assessment> page, Map<String, Object> conditions, Sort sort) {
        Wrapper<Assessment> wrapper = new EntityWrapper<>();
        this.generateSort(wrapper, sort);
        if (conditions.containsKey("yearId")) {
            wrapper.eq("year", conditions.get("yearId"));
        }

        page = this.selectPage(page, wrapper);

        for (Assessment assessment : page.getRecords()) {
            List<AssessmentDetail> assessmentDetails = findAssessmentDetailsByAssessmentIdAndHasWeight(assessment.getId());

            Wrapper<AssessmentPerson> personWrapper = new EntityWrapper<>();
            personWrapper.eq("assessment_id", assessment.getId());
            List<AssessmentPerson> assessmentPersons = assessmentPersonMapper.selectList(personWrapper);
            Set<Long> userIds = BeanUtils.getFiled(assessmentPersons, "userId", long.class);
            if (!userIds.isEmpty()) {
                List<User> users = userService.findUsersByIds(userIds);
                Map<Long, Double> scoreMap = new HashMap<>();
                String userNames = "";
                for (User user : users) {
                    userNames = userNames + user.getName() + " ";
                    List<AssessmentScore> assessmentScores = findAssessmentScoresByAssessmentIdAndUserId(assessment.getId(), user.getId());
                    if (null != assessmentScores && !assessmentScores.isEmpty() && assessmentScores.size() == assessmentDetails.size()) {
                        double score = 0.0;
                        for (AssessmentDetail assessmentDetail : assessmentDetails) {
                            for (AssessmentScore assessmentScore : assessmentScores) {
                                if (assessmentScore.getAssessmentDetailId().equals(assessmentDetail.getId())) {
                                    score += (double) assessmentScore.getScore() * (double) assessmentDetail.getWeight() / 100;
                                }
                            }
                        }
                        scoreMap.put(user.getId(), score);
                    }
                }
                assessment.setUserNames(userNames);
                double sumScore = 0.0;
                for (double score : scoreMap.values()) {
                    sumScore += score;
                }
                if (scoreMap.size() > 0) {
                    assessment.setScore(sumScore / scoreMap.size());
                }
            }

        }
        return page;
    }

    @Override
    public List<AssessmentDetail> getAndInitAssessmentDetails(Long assessmentId) {
        Assessment assessment = this.selectById(assessmentId);
        List<AssessmentDetail> assessmentDetails = findAssessmentDetailsByAssessmentId(assessmentId);
        if (!assessmentDetails.isEmpty()) {
            Iterator<AssessmentDetail> it = assessmentDetails.iterator();
            while (it.hasNext()) {
                AssessmentDetail detail = it.next();
                if (detail != null && detail.getTopTaskId() != null && detail.getTopTaskId() != 0) {
                    TargetTask targetTask = targetTaskService.getTargetTask(detail.getTopTaskId());
                    if (targetTask.getParentId() == 0 && !targetTask.getAssess()) {
                        assessmentDetailMapper.deleteById(detail.getId());
                        it.remove();
                    }
                }
            }

            return assessmentDetails;
        }

        List<TaskReportVo> report = targetTaskService.getTaskReportByReceiveDeptIdAndOriginatedDeptIdAndYear(assessment.getAssessmentedDeptId(), assessment.getAssessmentDeptId(), assessment.getYear());
        if (report.isEmpty()) {
            return null;
        }

        Map<Long, Integer> map = new HashMap<>();
        for (TaskReportVo taskReportVo : report) {
            int count;
            if (0 != taskReportVo.getTitle()) {
                if (map.containsKey(taskReportVo.getTitle())) {
                    count = map.get(taskReportVo.getTitle()) + 1;
                } else {
                    count = 1;
                }
                map.put(taskReportVo.getTitle(), count);
            }

            if (0 != taskReportVo.getLevelA()) {
                if (map.containsKey(taskReportVo.getLevelA())) {
                    count = map.get(taskReportVo.getLevelA()) + 1;
                } else {
                    count = 1;
                }
                map.put(taskReportVo.getLevelA(), count);
            }

            if (0 != taskReportVo.getLevelB()) {
                if (map.containsKey(taskReportVo.getLevelB())) {
                    count = map.get(taskReportVo.getLevelB()) + 1;
                } else {
                    count = 1;
                }
                map.put(taskReportVo.getLevelB(), count);
            }

            if (0 != taskReportVo.getLevelC()) {
                if (map.containsKey(taskReportVo.getLevelC())) {
                    count = map.get(taskReportVo.getLevelC()) + 1;
                } else {
                    count = 1;
                }
                map.put(taskReportVo.getLevelC(), count);
            }
        }

        int seq = 1;
        for (TaskReportVo taskReportVo : report) {
            if (0 == taskReportVo.getLevelA()) {
                if (map.containsKey(taskReportVo.getTitle()) && map.get(taskReportVo.getTitle()) > 1) {
                    continue;
                }
                taskReportVo.setLevelA(null);
            }

            if (0 == taskReportVo.getLevelB()) {
                if (map.containsKey(taskReportVo.getLevelA()) && map.get(taskReportVo.getLevelA()) > 1) {
                    continue;
                }
                taskReportVo.setLevelB(null);
            }

            if (0 == taskReportVo.getLevelC()) {
                if (map.containsKey(taskReportVo.getLevelB()) && map.get(taskReportVo.getLevelB()) > 1) {
                    continue;
                }
                taskReportVo.setLevelC(null);
            }

            if (taskReportVo != null && taskReportVo.getTitle() != null && taskReportVo.getTitle() != 0) {
                TargetTask targetTask = targetTaskService.getTargetTask(taskReportVo.getTitle());
                if (targetTask.getParentId() == 0 && !targetTask.getAssess()) {
                    continue;
                }
            }

            AssessmentDetail assessmentDetail = new AssessmentDetail();
            assessmentDetail.setAssessmentId(assessment.getId());
            assessmentDetail.setTopTaskId(taskReportVo.getTitle());
            assessmentDetail.setFirstTaskId(taskReportVo.getLevelA());
            assessmentDetail.setSecondTaskId(taskReportVo.getLevelB());
            assessmentDetail.setThirdTaskId(taskReportVo.getLevelC());
            assessmentDetail.setTopTaskDesc(taskReportVo.getTitleDesc());
            assessmentDetail.setFirstTaskDesc(taskReportVo.getLevelADesc());
            assessmentDetail.setSecondTaskDesc(taskReportVo.getLevelBDesc());
            assessmentDetail.setThirdTaskDesc(taskReportVo.getLevelCDesc());
            assessmentDetail.setAssessmentStandard(taskReportVo.getStandard());
            assessmentDetail.setSeq(seq);
            assessmentDetail.setYear(assessment.getYear());
            assessmentDetail.setAssessmentedDeptId(assessment.getAssessmentedDeptId());
            assessmentDetail.setAssessmentDeptId(taskReportVo.getDeptId());

            assessmentDetailMapper.insert(assessmentDetail);
            seq ++;
        }

        return findAssessmentDetailsByAssessmentId(assessment.getId());
    }

    @Override
    public List<AssessmentDetail> findAssessmentDetailsByAssessmentId(Long assessmentId) {
        Wrapper<AssessmentDetail> wrapper = new EntityWrapper<>();
        wrapper.eq("assessment_id", assessmentId);
        wrapper.orderBy("seq", true);
        return assessmentDetailMapper.selectList(wrapper);
    }

    @Override
    public List<AssessmentDetail> findAssessmentDetailsByAssessmentIdAndHasWeight(Long assessmentId) {
        Wrapper<AssessmentDetail> wrapper = new EntityWrapper<>();
        wrapper.eq("assessment_id", assessmentId);
        wrapper.gt("weight", 0);
        wrapper.orderBy("seq", true);
        return assessmentDetailMapper.selectList(wrapper);
    }


    @Override
    public boolean updateAssessmentDetails(List<AssessmentDetail> assessmentDetails) {
        if (assessmentDetails.isEmpty()) {
            return true;
        }

        for (AssessmentDetail assessmentDetail : assessmentDetails) {
            assessmentDetailMapper.updateById(assessmentDetail);
        }

        return true;
    }

    @Override
    public Assessment getAssessmentByYearAndAssessmentedDeptIdAndAssessmentDeptId(Long year, Long assessmentedDeptId, Long assessmentDeptId) {
        Wrapper<Assessment> wrapper = new EntityWrapper<>();
        wrapper.eq("assessment_dept_id", assessmentDeptId);
        wrapper.eq("assessmented_dept_id", assessmentedDeptId);
        wrapper.eq("year", year);
        return this.selectOne(wrapper);
    }

    @Override
    public List<Assessment> findAssessmentByYearAndAssessmentDeptId(Long year, Long assessmentDeptId) {
        Wrapper<Assessment> wrapper = new EntityWrapper<>();
        wrapper.eq("assessment_dept_id", assessmentDeptId);
        wrapper.eq("year", year);
        return this.selectList(wrapper);
    }

    @Override
    public List<Assessment> findAssessmentByYearAndAssessmentedDeptId(Long year, Long assessmentedDeptId) {
        Wrapper<Assessment> wrapper = new EntityWrapper<>();
        wrapper.eq("assessmented_dept_id", assessmentedDeptId);
        wrapper.eq("year", year);
        return this.selectList(wrapper);
    }

    @Override
    public AssessDetailTreeVo getAssessmentDetailTree(Long yearId) {
        User currentUser = getCurrentUser();
        TaskYear taskYear = targetTaskService.getTaskYear(yearId);
        AssessDetailTreeVo assessDetailTreeVo = new AssessDetailTreeVo();
        assessDetailTreeVo.setCode(taskYear.getCode());
        assessDetailTreeVo.setTitle(taskYear.getTitle());
        List<Assessment> assessments = findAssessmentByYearAndAssessmentDeptId(yearId, currentUser.getDeptId());

        if (null == assessments) {
            return assessDetailTreeVo;
        }
        List<AssessmentDetailVo> assessmentDetailVos = new ArrayList<>();
        for (Assessment assessment : assessments) {
            AssessmentPerson assessmentPerson = new AssessmentPerson();
            assessmentPerson.setAssessmentId(assessment.getId());
            assessmentPerson.setUserId(currentUser.getId());
            AssessmentPerson dbAssessmentPerson = assessmentPersonMapper.selectOne(assessmentPerson);
            if (null == dbAssessmentPerson) {

                continue;
            }

            List<AssessmentDetailVo> tmpAssessmentDetailVos = assessmentDetailMapper.findAssessmentDetailVosByAssessmentId(assessment.getId());
            if (null != tmpAssessmentDetailVos) {
                assessmentDetailVos.addAll(tmpAssessmentDetailVos);
            }
        }

        assessDetailTreeVo.setChildren(assessmentDetailVos);

        return assessDetailTreeVo;
    }

    @Override
    public AssessmentScore getAssessmentScoreByDetailIdAndUserId(Long detailId, Long userId) {
        AssessmentScore assessmentScore = new AssessmentScore();
        assessmentScore.setAssessmentDetailId(detailId);
        assessmentScore.setUserId(userId);

        return assessmentScoreMapper.selectOne(assessmentScore);
    }

    @Override
    public Boolean deletAssessment(Long assessmentId) {
        this.deleteById(assessmentId);

        Wrapper<AssessmentDetail> wrapperDetail = new EntityWrapper<>();
        wrapperDetail.eq("assessment_id", assessmentId);
        assessmentDetailMapper.delete(wrapperDetail);

        Wrapper<AssessmentPerson> wrapperPerson = new EntityWrapper<>();
        wrapperPerson.eq("assessment_id", assessmentId);
        assessmentPersonMapper.delete(wrapperPerson);

        Wrapper<AssessmentScore> wrapperScore = new EntityWrapper<>();
        wrapperScore.eq("assessment_id", assessmentId);
        assessmentScoreMapper.delete(wrapperScore);

        return true;
    }

    @Override
    public AssessmentDetailShowVo getAssessmentDetailShowVo(Long detailId) {
        AssessmentDetail assessmentDetail = assessmentDetailMapper.selectById(detailId);
        if (null == assessmentDetail) {
            throw new ServiceException("该考核不存在");
        }
        Long taskId;
        if (null != assessmentDetail.getThirdTaskId()) {
            taskId = assessmentDetail.getThirdTaskId();
        } else if (null != assessmentDetail.getSecondTaskId()) {
            taskId = assessmentDetail.getSecondTaskId();
        } else if (null != assessmentDetail.getFirstTaskId()) {
            taskId = assessmentDetail.getFirstTaskId();
        } else {
            taskId = assessmentDetail.getTopTaskId();
        }
        TargetTask targetTask = targetTaskService.getTargetTask(taskId);
        AssessmentDetailShowVo assessmentDetailShowVo = new AssessmentDetailShowVo();
        assessmentDetailShowVo.setTargetTask(targetTask);
        assessmentDetailShowVo.setId(detailId);
        assessmentDetailShowVo.setAssessmentId(assessmentDetail.getAssessmentId());

        User currentUser = getCurrentUser();
        AssessmentScore assessmentScore = getAssessmentScoreByDetailIdAndUserId(detailId, currentUser.getId());
        if (null == assessmentScore) {
            return assessmentDetailShowVo;
        }

        assessmentDetailShowVo.setRemark(assessmentScore.getRemark());
        assessmentDetailShowVo.setScore(assessmentScore.getScore());

        return assessmentDetailShowVo;
    }

    @Override
    public AssessmentScore createAssessmentScore(AssessmentScore assessmentScore) {
        User currrentUser = getCurrentUser();
        AssessmentScore selectAssessmentScore = new AssessmentScore();
        selectAssessmentScore.setUserId(currrentUser.getId());
        selectAssessmentScore.setAssessmentDetailId(assessmentScore.getAssessmentDetailId());

        AssessmentScore dbAssessmentScore = assessmentScoreMapper.selectOne(selectAssessmentScore);
        if (null != dbAssessmentScore) {
            assessmentScore.setId(dbAssessmentScore.getId());
            assessmentScoreMapper.updateById(assessmentScore);

            return assessmentScore;
        }

        assessmentScore.setUserId(currrentUser.getId());
        assessmentScoreMapper.insert(assessmentScore);

        return assessmentScore;
    }

    @Override
    public List<AssessmentScore> findAssessmentScoresByAssessmentIdAndUserId(Long assessmentId, Long userId) {
        Wrapper<AssessmentScore> personWrapper = new EntityWrapper<>();
        personWrapper.eq("assessment_id", assessmentId);
        personWrapper.eq("user_id", userId);
        return assessmentScoreMapper.selectList(personWrapper);
    }

    @Override
    public List<User> findScoreUsersByAssessmentId(Long assessmentId) {
        Wrapper<AssessmentScore> personWrapper = new EntityWrapper<>();
        personWrapper.eq("assessment_id", assessmentId);
        List<AssessmentScore> assessmentScore = assessmentScoreMapper.selectList(personWrapper);

        Set<Long> userIds = BeanUtils.getFiled(assessmentScore, "userId", long.class);
        if (!userIds.isEmpty()) {
            return userService.findUsersByIds(userIds);
        }

        return null;
    }

    @Override
    public List<User> findAssessPersonsByAssessmentId(Long assessmentId) {
        Wrapper<AssessmentPerson> personWrapper = new EntityWrapper<>();
        personWrapper.eq("assessment_id", assessmentId);
        List<AssessmentPerson> assessmentPersons = assessmentPersonMapper.selectList(personWrapper);

        Set<Long> userIds = BeanUtils.getFiled(assessmentPersons, "userId", long.class);
        if (!userIds.isEmpty()) {
            return userService.findUsersByIds(userIds);
        }

        return null;
    }
}
